package com.wdz;

import com.baomidou.mybatisplus.enums.FieldFill;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.toolkit.StringUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
//import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

/**
 * <p>
 * 代码生成器
 * </p>
 */
public class MpGenerator {

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    private int type;

    public void scanner2(DataSourceConfig dsc) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择登录的数据库：(0：测试数据库-dongzhebk(博客)，1：服务器数据库,3:测试数据库-resourcess(资源宝库))");
        if (scanner.hasNext()) {
            type = scanner.nextInt();
            if (type == 0) {
                dsc.setUsername("root");
                dsc.setPassword("19990930");
                dsc.setUrl("jdbc:mysql://106.52.65.18:3306/bd_dongzhebk?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true");
                return;
            } else if (type == 1) {
                dsc.setUsername("root");
                dsc.setPassword("19990930");
                dsc.setUrl("jdbc:mysql://106.52.65.18:3306/dongzhebk?useUnicode=true&characterEncoding=utf8");
                return;
            } else if (type == 3) {
                dsc.setUsername("root");
                dsc.setPassword("19990930");
                dsc.setUrl("jdbc:mysql://106.52.65.18:3306/resourcess?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true");
                return;
            }
        }
        throw new MybatisPlusException("请输入正确的数字！");
    }

    public PackageConfig getPackageConfig() {
        PackageConfig pc = new PackageConfig();
        if (type == 3) {
            pc.setParent("com.wdz.tofs");
        } else {
            pc.setParent("com.wdz");
        }
        pc.setModuleName(scanner("模块名"));
        pc.setEntity("entity");
        pc.setController(null);
        return pc;
    }
    /**
     * 获取表字段信息
     */
    public ResultSetMetaData getMetaData(DataSourceConfig dsc,String tableName){
        Connection connection = dsc.getConn();
        try {
            try (PreparedStatement preparedStatement = connection.prepareStatement("select * from " + tableName)) {
                return preparedStatement.executeQuery().getMetaData();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * <p>
     * MySQL 生成演示
     * </p>
     */
    public static void main(String[] args) {
        AutoGenerator mpg = new AutoGenerator();
        MpGenerator mpGenerator = new MpGenerator();
        // 选择 freemarker 引擎，默认 Veloctiy
        //mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        gc.setOpen(false);
        gc.setAuthor("吴传逞");
        String oPath = System.getProperty("user.dir");//得到当前项目的路径
        gc.setOutputDir(oPath + "/core_database/src/main/java/");   //生成文件输出根目录
        //gc.setOutputDir("G://dongzheBK/core/src/main/java");
        gc.setFileOverride(false);// 是否覆盖同名文件，默认是false
        gc.setActiveRecord(true);// 不需要ActiveRecord特性的请改为false
        gc.setEnableCache(false);// XML 二级缓存
        gc.setBaseResultMap(true);// XML ResultMap
        gc.setBaseColumnList(false);// XML columList
        gc.setIdType(IdType.UUID);
        /* 自定义文件命名，注意 %s 会自动填充表实体属性！ */
        // gc.setMapperName("%sDao");
        // gc.setXmlName("%sDao");
        // gc.setServiceName("MP%sService");
        // gc.setServiceImplName("%sServiceDiy");
        // gc.setControllerName("%sAction");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setTypeConvert(new MySqlTypeConvert() {
            // 自定义数据库表字段类型转换【可选】
            @Override
            public DbColumnType processTypeConvert(String fieldType) {
                // 注意！！processTypeConvert 存在默认类型转换，如果不是你要的效果请自定义返回、非如下直接返回。
                if (fieldType.equals("datetime")) {
                    fieldType = "String";
                }
                System.out.println("转换类型：" + fieldType);
                return super.processTypeConvert(fieldType);
            }
        });
        dsc.setDriverName("com.mysql.jdbc.Driver");

       /* dsc.setUsername("root");
        dsc.setPassword("19990930");
        dsc.setUrl("jdbc:mysql://212.64.22.159:3306/dongzheBK?useUnicode=true&characterEncoding=utf8");*/
        mpGenerator.scanner2(dsc);
        mpg.setDataSource(dsc);
        // 包配置
        PackageConfig pc = mpGenerator.getPackageConfig();
        mpg.setPackageInfo(pc);
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();

        // strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
        strategy.setTablePrefix(new String[]{""});// 此处可以修改为您的表前缀
        //下划线转驼峰命名法
        strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
        //自动填充设置
        List<TableFill> tableFillList = new ArrayList<TableFill>();
        tableFillList.add(new TableFill("create_date", FieldFill.INSERT));//设置为插入时自动填充
        tableFillList.add(new TableFill("update_date", FieldFill.INSERT_UPDATE));//设置为更新时自动填充
        strategy.setTableFillList(tableFillList);
        strategy.setRestControllerStyle(true);
        String tables = mpGenerator.scanner("表名,以逗号隔开需要生成的表");
        if (tables.length() != 0) {
            if ((tables.charAt(tables.length() - 1)) == ',') {
                tables = tables.substring(0, tables.length() - 1);
            }
            String[] tabless = tables.split(",");

            strategy.setInclude(tabless); // 需要生成的表
        }
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
                Map<String,Object> map = new HashMap<>();
                this.setMap(map);
            }
        };

        // 如果模板引擎是 freemarker
        // String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        String templatePath = "/templates/mapper.xml.vm";
        String entityPath = "/template/entity.java.vm";
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                List<TableField> list = tableInfo.getFields();
                Iterator<TableField> iterator = list.iterator();
                ResultSetMetaData resultSetMetaData = mpGenerator.getMetaData(dsc,tableInfo.getName());
                int i = 1;
                while (iterator.hasNext()){
                    Map<String,Object> map = new HashMap<String,Object>();
                    try {
                        //在数据库中字符最大长度
                        if("DATETIME".equals(resultSetMetaData.getColumnTypeName(i))){
                            map.put("length",0);
                        }else{
                            map.put("length",resultSetMetaData.getColumnDisplaySize(i));
                        }
                        //类型
                        map.put("type",resultSetMetaData.getColumnTypeName(i));
                        //是否为null
                        map.put("nullable",resultSetMetaData.isNullable(i));
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    i++;
                    iterator.next().setCustomMap(map);
                }
                return oPath + "/core_database/src/main/resources/mapper/" + mpGenerator.change(tableInfo.getEntityName())+ "/"+tableInfo.getEntityName() + "Mapper.xml";
            }
        });
        focList.add(new FileOutConfig(entityPath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！

                return oPath + "/core_database/src/main/java/com/wdz/" + mpGenerator.change(tableInfo.getEntityName())+ "/entity/"+tableInfo.getEntityName() + ".java";
            }
        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        //不生成controller
        TemplateConfig tc = new TemplateConfig();
        tc.setController(null);
        tc.setXml(null);
        //tc.setEntity("template/entity.java");
        mpg.setTemplate(tc);
        // 执行生成
        mpg.execute();

        // 打印注入设置【可无】
//        System.err.println(mpg.getCfg().getMap().get("abc"));
    }
    /**
     * 全部转换为小写
     *
     * @param str 需要转换的参数
     * @return 返回替换后字符串
     */
    private String change(String str) {
        char[] cs = str.toCharArray();
        StringBuilder rstr = new StringBuilder();
        for (char c : cs) {
            //如果输入的是大写，+32即可得到小写
            if (c >= 'A' && c <= 'Z') {
                c += 32;
            }
            rstr.append(c);
        }
        return rstr.toString();
    }
}
